<script context="module">
  export const position = 'PrependContainer';
  export const defaults = {
    fallback: true,
    icon: null,
    tag: null,
    title: null,
    text: null,
    options: {},
  };

  function requestPermission() {
    if (
      typeof Notification !== 'undefined' &&
      'requestPermission' in Notification
    ) {
      Notification.requestPermission();
    } else if ('webkitNotifications' in window) {
      window.webkitNotifications.requestPermission();
    }
  }
  export { requestPermission as permission };

  const Notification = window.Notification;

  let notify = (title, options, onclick, onclose) => {
    // Memoize based on feature detection.
    if ('Notification' in window) {
      notify = (title, options, onclick, onclose) => {
        const notice = new Notification(title, options);
        if ('NotificationEvent' in window) {
          notice.addEventListener('notificationclick', onclick);
          notice.addEventListener('close', onclose);
        } else if ('addEventListener' in notice) {
          notice.addEventListener('click', onclick);
          notice.addEventListener('close', onclose);
        } else {
          notice.onclick = onclick;
          notice.onclose = onclose;
        }
        return notice;
      };
    } else if ('mozNotification' in navigator) {
      notify = (title, options, onclick, onclose) => {
        // Gecko < 22
        const notice = navigator.mozNotification
          .createNotification(title, options.body, options.icon)
          .show();
        notice.onclick = onclick;
        notice.onclose = onclose;
        return notice;
      };
    } else if ('webkitNotifications' in window) {
      notify = (title, options, onclick, onclose) => {
        const notice = window.webkitNotifications.createNotification(
          options.icon,
          title,
          options.body
        );
        notice.onclick = onclick;
        notice.onclose = onclose;
        return notice;
      };
    } else {
      notify = (title, options, onclick, onclose) => {
        return null;
      };
    }
    return notify(title, options, onclick, onclose);
  };

  function checkPermission() {
    if (typeof Notification !== 'undefined' && 'permission' in Notification) {
      return Notification.permission === 'granted';
    } else if ('webkitNotifications' in window) {
      return window.webkitNotifications.checkPermission() == 0;
    }
    return false;
  }

  let _permission = checkPermission();
</script>

<script>
  // The PNotify notice.
  export let self = null;

  export let fallback = defaults.fallback;
  export let icon = defaults.icon;
  export let tag = defaults.tag;
  export let title = defaults.title;
  export let text = defaults.text;
  export let options = defaults.options;

  let _desktop;
  // Animation should always be 'none' for desktop notices, but remember
  // the old animation so it can be recovered.
  let _oldAnimation = 'none';
  let _icon;
  let _tag;

  $: {
    if (self.animation !== 'none') {
      _oldAnimation = self.animation;
    }

    // This is necessary so desktop notices don't cause spacing problems
    // when positioning.
    if (self.getAnimatingClass() !== '' && _permission) {
      self.setAnimatingClass('');
    }

    if (!_permission && self.hasModuleClass('elem', 'pnotify-desktop-hide')) {
      self.removeModuleClass('elem', 'pnotify-desktop-hide');
      self.animation = _oldAnimation;
    } else if (
      _permission &&
      !self.hasModuleClass('elem', 'pnotify-desktop-hide')
    ) {
      self.addModuleClass('elem', 'pnotify-desktop-hide');
      self.animation = 'none';
      genNotice();
    }
  }

  $: {
    self.setModuleHandled(_permission);
  }

  self.on('pnotify:beforeOpen', () => {
    if (!_permission) {
      requestPermission();
      return;
    }
    if (_desktop && 'show' in _desktop) {
      self.setModuleOpen(true);
      _desktop.show();
    }
  });

  self.on('pnotify:beforeClose', () => {
    if (!_permission) {
      return;
    }
    if (_desktop && 'close' in _desktop) {
      _desktop.close();
      self.setModuleOpen(false);
    }
  });

  _permission = checkPermission();

  if (_permission) {
    self.addModuleClass('elem', 'pnotify-desktop-hide');
    self.animation = 'none';
    genNotice();
  } else if (!fallback) {
    // Keep the notice from opening if fallback is false.
    self.autoOpen = false;
  }

  function genNotice() {
    if (icon === null) {
      switch (self.type) {
        case 'error':
          _icon =
            '';
          break;
        case 'success':
          _icon =
            '';
          break;
        case 'info':
          _icon =
            '';
          break;
        case 'notice':
        default:
          _icon =
            '';
          break;
      }
    } else if (icon === false) {
      _icon = null;
    } else {
      _icon = icon;
    }

    if (!_tag || tag !== null) {
      _tag =
        tag === null ? `PNotify-${Math.round(Math.random() * 1000000)}` : tag;
    }

    const desktopOptions = {
      body: text || self.text,
      tag: _tag,
    };
    if (!self.hide) {
      desktopOptions.requireInteraction = true;
    }
    if (_icon !== null) {
      desktopOptions.icon = _icon;
    }
    Object.apply(desktopOptions, options);

    _desktop = notify(
      title || self.title,
      desktopOptions,
      () => {
        self.fire && self.fire('click', { target: _desktop });
      },
      () => {
        self.close && self.close();
      }
    );

    if (!('close' in _desktop) && 'cancel' in _desktop) {
      _desktop.close = () => {
        _desktop.cancel();
      };
    }
  }
</script>

<style>
  :global([data-pnotify].pnotify-desktop-hide) {
    left: -10000px !important;
    display: none !important;
  }
</style>
